/*
 * Copyright (c) 2009 Jesse McLaughlin (nzjess@gmail.com)
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *         http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.travelfusion.xmlclient.ri.samples;

import static org.travelfusion.xmlclient.ri.samples.SamplesUtil.flightToString;
import static org.travelfusion.xmlclient.ri.samples.SamplesUtil.todayPlusDays;

import java.util.ArrayList;
import java.util.List;

import org.travelfusion.xmlclient.TfXClient;
import org.travelfusion.xmlclient.ri.TfXClientFactory;
import org.travelfusion.xmlclient.ri.xobject.plane.XCheckRoutingRequest;
import org.travelfusion.xmlclient.ri.xobject.plane.XCheckRoutingResponse;
import org.travelfusion.xmlclient.ri.xobject.plane.XFlight;
import org.travelfusion.xmlclient.ri.xobject.plane.XStartRoutingRequest;
import org.travelfusion.xmlclient.ri.xobject.plane.XStartRoutingResponse;

/**
 * 'Hello World' for the TRAVELfusion TripPlannerXML API Java client library.
 * <p>
 * Demonstrates the quickest way to obtain a client instance, send some commands to the TripPlannerXML service, and
 * display the results.
 * <p>
 * The example used here is a straight-forward search for return flights between London and Madrid.
 * <p>
 * <strong>IMPORTANT!</strong>
 * <p>
 * You need an XML login ID to use the TripPlannerXML service. Get one before running this code. To get one, you'll need
 * to <a href="https://xml.travelfusion.com/registration/">register</a> as an affiliate with TRAVELfusion.
 * 
 * @author Jesse McLaughlin (nzjess@gmail.com)
 */
public class HelloTripPlanner {

  /**
   * Application entry point. Pass in your XML login ID.
   */
  public static void main(String... args) throws Exception {
    // get for xml login id argument from command line
    String loginId = null;
    if (args.length > 0) {
      loginId = args[0];
    }
    else {
      System.err.println("Usage: HelloTripPlanner <XML login ID>");
      System.exit(1);
    }

    // create a client factory in the standard configuration, passing in our login id
    TfXClientFactory factory = new TfXClientFactory(loginId);

    // use the factory to obtain a client instance
    TfXClient client = factory.getClient();

    // create a StartRouting request: London to Madrid (return)
    XStartRoutingRequest startRoutingRequest = new XStartRoutingRequest();
    // from london 'all airports'
    startRoutingRequest.setOrigin("LON");
    startRoutingRequest.setOriginType("citycode");
    startRoutingRequest.setOriginRadius(75000); // 75km
    // to madrid airport
    startRoutingRequest.setDestination("MAD");
    startRoutingRequest.setDestinationType("airportcode");
    startRoutingRequest.setDestinationRadius(0);
    // leaving in a week
    startRoutingRequest.setOutwardDate(todayPlusDays(7));
    // returning a week after that
    startRoutingRequest.setReturnDate(todayPlusDays(14));

    // Send the StartRouting command. This command does not actually return the search results directly. Instead, it
    // returns a 'handle' to the results, in the form of a routing ID (which is just a string). We can use this routing
    // ID to issue one or more subsequent CheckRouting commands. These poll the service for the results themselves (see
    // further below).
    System.out.println("Initiating flight search...\n");
    XStartRoutingResponse startRoutingResponse = (XStartRoutingResponse)client.invoke(startRoutingRequest);

    // create a CheckRouting request, using the routing ID we've just received back from the StartRouting response
    XCheckRoutingRequest checkRoutingRequest = new XCheckRoutingRequest();
    checkRoutingRequest.setRoutingId(startRoutingResponse.getRoutingId());
    checkRoutingRequest.setSegmentsEnabled(false); // extra for experts

    // somewhere to accumulate the results into
    List<XFlight> outwardFlights = new ArrayList<XFlight>();
    List<XFlight> returnFlights = new ArrayList<XFlight>();

    // Send the CheckRouting command(s). We can send this command more than once, since this command is designed to poll
    // the server. On each invocation, whatever results are ready will be returned (the service ensures that results
    // from are not repeated across multiple calls).
    int maxCheckRoutingCalls = 3;
    while (maxCheckRoutingCalls-- > 0) {
      // wait a little while, to give new results time to become available
      Thread.sleep(5000);

      // invoke the client to poll for the results
      System.out.println("Polling for results... please wait");
      XCheckRoutingResponse checkRoutingResponse = (XCheckRoutingResponse)client.invoke(checkRoutingRequest);

      // accumulate the results
      outwardFlights.addAll(checkRoutingResponse.getOutwardFlights());
      returnFlights.addAll(checkRoutingResponse.getReturnFlights());

      // we can also use the CheckRouting command response to determine if we've polled all the available results yet
      if (checkRoutingResponse.getCompletedRouterCount() == checkRoutingResponse.getRouterSummaries().size()) {
        break;
      }
    }

    // now the interesting bit... let's see what are the cheapest flights for our trip!

    // output outward flights
    System.out.println("\nOutward Flights:");
    for (XFlight flight : outwardFlights) {
      System.out.println(flightToString(flight));
    }
    System.out.println(outwardFlights.size() + " outward flights found.");

    // output return flights
    System.out.println("\nReturn Flights:");
    for (XFlight flight : returnFlights) {
      System.out.println(flightToString(flight));
    }
    System.out.println(returnFlights.size() + " return flights found.");

    // done
    System.out.println("\nDone.");
  }
}
